Checkbox manipulation
Our contact form also has a Miscellaneous section, which contains a list of checkboxes.
To round out our
enhancements to the contact form, we'll help the user manage this list.
A group of 10 checkboxes can be daunting, especially if the user wishes
to click most or all of them. An option to check, or uncheck, all of
the checkboxes comes in handy in this type of situation. So, let's
create one.
To begin, we create a new<li> element, fill it with a<label>, inside which we place<input type="checkbox" id="discover-all"> and some text, and prepend it all to the<ul> element inside<li class="discover">:
$(document).ready(function() {
$('<li></li>')
.html('<label><input type="checkbox" id="discover-all" />' +
' <em>check all</em></label>')
.prependTo('li.discover > ul');
});
Now we have a new checkbox with a label that reads check all. But it doesn't do anything yet. We need to attach the .click() method to it:
$(document).ready(function() {
$('<li></li>')
.html('<label><input type="checkbox" id="discover-all" />' +
' <em>check all</em></label>')
.prependTo('li.discover > ul');
$('#discover-all').click(function() {
var $checkboxes = $(this).parents('ul:first')
.find(':checkbox');
if (this.checked) {
$checkboxes.attr('checked', true);
} else {
$checkboxes.attr('checked', '');
}
});
});
Inside this event handler, we first set the $checkboxes
variable, which consists of a jQuery object containing every checkbox
within the current list. With the variable set, manipulating the
checkboxes becomes a matter of checking them if the check all checkbox is checked, and unchecking them if the check all one is unchecked.
A finishing touch can be applied to this checkbox feature by adding a checkall class to the check all checkbox's label, and changing its text to un-check all after it has been checked by the user:
$(document).ready(function() {
$('<li></li>')
.html('<label><input type="checkbox" id="discover-all" />' +
' <em>check all</em></label>')
.prependTo('li.discover > ul');
$('#discover-all').click(function() {
var $checkboxes = $(this) .parents('ul:first')
.find(':checkbox');
if (this.checked) {
$(this).next().text(' un-check all');
$checkboxes.attr('checked', true);
} else {
$(this).next().text(' check all');
$checkboxes.attr('checked', '');
};
})
.parent('label').addClass('checkall');
});
The group of checkboxes, along with the check all box, now looks like this:
And with the check all box checked, the group looks like this:
The finished code
Here it is, the finished code for the contact form:
$(document).ready(function() {
// Enhance style of form elements.
$('legend').each(function(index) {
$(this).replaceWith('<h3>' + $(this).text() + '</h3>');
});
var requiredFlag = ' * ';
var conditionalFlag = ' ** ';
var requiredKey = $('input.required:first')
.next('span').text();
var conditionalKey = $('input.conditional:first')
.next('span').text();
requiredKey = requiredFlag +
requiredKey.replace(/^\((.+)\)$/,'$1');
conditionalKey = conditionalFlag +
conditionalKey.replace(/^\((.+)\)$/,'$1');
$('<p></p>')
.addClass('field-keys')
.append(requiredKey + '<br />')
form, stylingcontact form code.append(conditionalKey)
.insertBefore('#contact');
$('form :input')
.filter('.required')
.next('span').text(requiredFlag).end()
.prev('label').addClass('req-label').end()
.end()
.filter('.conditional')
.next('span').text(conditionalFlag);
// Checkbox toggle: conditional text inputs.
$('input.conditional').next('span').andSelf().hide()
.end().end()
.each(function() {
var $thisInput = $(this);
var $thisFlag = $thisInput.next('span');
$thisInput.prev('label').find(':checkbox')
.attr('checked', false)
.click(function() {
if (this.checked) {
$thisInput.show().addClass('required');
$thisFlag.show();
$(this).parent('label').addClass('req-label');
} else {
$thisInput.hide().removeClass('required').blur();
$thisFlag.hide();
$(this).parent('label').removeClass('req-label');
}
});
});
// Validate fields on blur.
$('form :input').blur(function() {
$(this).parents('li:first').removeClass('warning')
.find('span.error-message').remove();
if ($(this).hasClass('required')) {
var $listItem = $(this).parents('li:first');
if (this.value == '') {
var errorMessage = 'This is a required field';
if ($(this).is('.conditional')) {
errorMessage += ', when its related checkbox is
checked';
}
$('<span></span>')
.addClass('error-message')
.text(errorMessage)
.appendTo($listItem);
$listItem.addClass('warning');
}
}
if (this.id == 'email') {
form, stylingcontact form codevar $listItem = $(this).parents('li:first');
if ($(this).is(':hidden')) {
this.value = '';
}
if (this.value != '' &&
!/.+@.+\.[a-zA-Z]{2,4}$/.test(this.value)) {
var errorMessage = 'Please use proper e-mail format'
+ ' (e.g. [email protected])';
$('<span></span>')
.addClass('error-message')
.text(errorMessage)
.appendTo($listItem);
$listItem.addClass('warning');
}
}
});
// Validate form on submit.
$('form').submit(function() {
$('#submit-message').remove();
$(':input.required').trigger('blur');
var numWarnings = $('.warning', this).length;
if (numWarnings) {
var fieldList = [];
$('.warning label').each(function() {
fieldList.push($(this).text());
});
$('<div></div>')
.attr({
'id': 'submit-message',
'class': 'warning'
})
.append('Please correct errors with the following ' +
numWarnings + ' fields:<br />')
.append('• ' + fieldList.join('<br />• '))
.insertBefore('#send');
return false;
};
});
// Checkboxes
form, stylingcontact form code$('form :checkbox').removeAttr('checked');
// Checkboxes with (un)check all.
$('<li></li>')
.html('<label><input type="checkbox" id="discover-all" />' +
' <em>check all</em></label>')
.prependTo('li.discover > ul');
$('#discover-all').click(function() {
var $checkboxes = $(this) .parents('ul:first')
.find(':checkbox');
if (this.checked) {
$(this).next().text(' un-check all');
$checkboxes.attr('checked', true);
} else {
$(this).next().text(' check all');
$checkboxes.attr('checked', '');
};
})
.parent('label').addClass('checkall');
});
Although we've made
significant improvements to the contact form, there is still much that
could be done. Validation, for example, comes in a number of varieties.
For a flexible validation plugin, visit http://plugins.jquery.com/project/validate/.